#################################################################################
#
# Copyright (c) 2006 Michigan State University
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#################################################################################

#################################################################################
#
#	Author:
#		Nathan Collins <npcollins@gmail.com>
#
#################################################################################

"""
Utility functions.
"""

# imports
import codecs
import re
import types
import urllib

def writefile(filename, req = None, values = ()):
	"""
	Open file and return it. If a request object is passed,
	then write to the request object and return an empty
	string. Strings are unicode.
	"""
	# write string to return
	writestring = u''

	# read in file
	fh = codecs.open(filename, 'r', 'utf-8')
	filestring = fh.read()
	fh.close()

	# insert values if passed

	# handle utf8 chars
	filestring = filestring.decode('utf-8')
	values = list(values)
	for k in range(len(values)):
		values[k] = values[k].decode('utf-8')

	values = tuple(values)

	if values != ():
		filestring = filestring % values

	filestring = filestring.encode('utf-8')

	# if request object was passed
	if req is not None:
		# then write to the request object
		req.write(filestring)

	# if no request object was passed
	else:
		# then we will simply return the contents
		writestring = filestring

	# return the write string
	return writestring


def writejavascript(javascript, req = None):
	"""
	Given the name of a javascript file, print the script tag to the
	request object. If no request object is passed, return as a
	string.
	"""
	# the javascript file
	filestring = ''

	# javascript format string
	jsformat = '<script language="Javascript" type="text/javascript" src="%s"></script>'

	# check file for .js extension
	if len(javascript) > 3 and javascript[-3:] == '.js':
		filestring = javascript

	# otherwise, add the .js extension
	else:
		filestring = javascript + '.js'

	# string to write or return
	writestring = jsformat % filestring

	# if request object was passed
	if req is not None:
		# then write to the request object
		req.write(writestring)
		# clear the writesting for return
		writestring = ''

	# if no request object was passed, we return the full string
	pass

	# return the write string
	return writestring


def commas(number):
	"""
	Given a large number, place commas in it and return as string.
	"""
	com = str(number)
	firstC = len(com) % 3
	if not firstC: firstC = 3
	firstN, restN = com[:firstC], com[firstC:]
	allN = [firstN] + [restN[c:c+3] for c in range(0,len(restN),3)]
	return ','.join(allN)


def uni2asc(unistr):
	"""
	Given a string, check to see if it is unicode. If so, escape unicode chars
	with their XML character reference.
	"""
	if type(unistr) is UnicodeType:
		return unistr.encode('ascii','xmlcharrefreplace')
	else:
		return data

def shorten(s, length, min = 0):
	"""
	Shorten string to a given length. If a minimum is specified, then
	return empty if string is less than the minimum.
	"""
	# if the length requested is 0, return the string unmodified
	if length == 0: return s

	# if the length of the string is less than the minimum, return empty
	if len(s) < min: return ''

	# if the length of the string is longer than allowed, then trim it
	if len(s) > length:
		return s[:length] + ' ...'

	# otherwise the string is just fine as is
	else: return s


def makehash(unhashed):
	"""
	Generate a new MD5 hash of the string passed in.
	"""
	# create new hasher
	hasher = md5.new()

	# pass the string to the hasher
	hasher.update(unhashed)

	# return the hash in hex form
	return hasher.hexdigest()


def sortlistdict(listdict, dictkey):
	"""
	Sort a list of dictionaries by a given dict key.
	"""
	# pull the values for the given key into a list
	sortlist = [d[dictkey] for d in listdict]

	# generate a dict wherer the sortlist are the keys and listdict are the values
	sortdict = dict(zip(sortlist,listdict))
	
	# sort sortdict by its keys and generate a list of values
	newlistdict = [sortdict[k] for k in sorted(sortdict.keys())]

	# return the sorted listdict
	return newlistdict


def boldify(text, words):
	"""
	Given a list of words/phrases, bold all instances of them in a text.

	If a list is passed in for text, return a dict where the keys are made
	from the list and the value is the bolded version.
	"""
	# catch processing sinks
	if len(text) > 8192: return text
	
	# list passed flag
	islist = 0

	# list return dict
	listret = {}

	# catch list passed
	if type(text) == types.ListType:
		islist = 1

	# a catch all
	try:
		# bold each word
		for word in words:
			# escape re chars
			word = word.replace('.', '\\.')

			# ignore single/empty words
			if len(word) > 1:
				bld = re.compile(u'\\b(%s)\\b' % word, re.IGNORECASE | re.UNICODE)
				# if a list was passed
				if islist == 1:
					for value in text:
						listret[value] = bld.sub(u'<b>\\1</b>',value)

					# assign dict for return
					text = listret

				# normal text
				else:
					text = bld.sub(u'<b>\\1</b>', text)
	except:
		# errors shouldn't prevent page from displaying
		pass
	return text


def keytolist(sDict, sKey):
	"""
	If a dictionary has a given key, place the value of the key
	and return it as a list containing just that value.
	"""
	if sDict.has_key(sKey) and len(sDict[sKey].strip()) > 0:
		return [sDict[sKey].strip()]
	return []


# check to see if it is an empty string after trimming
def empty(field, fLen = 0):
	"""
	Check to see if a given string is empty, or if a length is passed,
	less than that length.
	"""
	if len(field.strip()) > fLen:
		return 0
	return 1


# generate a tracking url for a result click
def maketrackurl(url,recHash,terms):
	"""
	Given a url, record hash, and terms; return a url to be used for
	tracking clicks.
	"""
	if not empty(url):
		# quote terms if possible
		try:
			terms = urllib.quote_plus(terms)
		except:
			terms = 'a'	# dummy stopword

		return "url.py?s=%s&i=%s&u=%s" \
			% (terms, recHash, urllib.quote(url))
	else:
		return ''


# escape apostrophes
def aposescape(text):
	"""
	Escape ' in the text with &apos;
	"""
	text = text.replace("'", '&#39;')
	
	return text


# escape < and >
def gtltescape(text):
	"""
	Escape < with &lt; and > with &gt;
	"""
	text = text.replace("<", "&lt;")
	text = text.replace(">", "&gt;")

	return text


# clean up a title for google search
def cleantitle(titlestr):
	titlecapture = re.compile(r'^(.*)\s*(--|/)')

	titleresult = titlecapture.search(titlestr)
	if titleresult is not None:
		newtitle = titleresult.groups()[0].strip()
		if len(newtitle) > 0:
			titlestr = newtitle

	return titlestr


# eof

